package com.zhang.eurekaclient;

import com.zhang.eurekaclient.config.UserContextInterceptor;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.security.oauth2.client.DefaultOAuth2ClientContext;
import org.springframework.security.oauth2.client.OAuth2ClientContext;
import org.springframework.security.oauth2.client.OAuth2RestTemplate;
import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.Collections;
import java.util.List;

/**
 * 其中
 * spring.sleuth.web.client.enable为true设置的是web开启sleuth功能
 * spring.sleuth.sampler.probability可以设置为小数，最大值为1.0，当设置为1.0时就是链路数据100%收集到zipkin-server，当设置为0.1时，即10%概率收集链路数据
 * spring.zipkin.base-url设置zipkin-server的地址。
 * http://localhost:9411/zipkin/
 *
 *
 * 注解@EnableEurekaClient上有@EnableDiscoveryClient注解，
 * 可以说基本就是EnableEurekaClient有@EnableDiscoveryClient的功能，另外上面的注释中提到，其实@EnableEurekaClientz注解就是一种方便使用eureka的注解而已，
 * 可以说使用其他的注册中心后，都可以使用@EnableDiscoveryClient注解，
 * 但是使用@EnableEurekaClient的情景，就是在服务采用eureka作为注册中心的时候，使用场景较为单一。
 *
 * 注册、续约、下线
 *
 * >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 *
 * 2019-08-29 add
 * 资源服务器通过 @EnableResourceServer 注解来开启一个 OAuth2AuthenticationProcessingFilter 类型的过滤器
 * 通过继承 ResourceServerConfigurerAdapter 类来配置资源服务器
 *
 * >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 *
 * @author zhanghaidong
 */
@EnableResourceServer
@RestController
@EnableEurekaClient
@SpringBootApplication
public class EurekaClientApplication {

    public static void main(String[] args) {
        SpringApplication.run(EurekaClientApplication.class, args);
    }

    @Value("${server.port}")
    private String port;

    @RequestMapping(value = "/hello", method = RequestMethod.GET)
    public String home(@RequestParam(value = "name", defaultValue = "zhd") String name) {
        return "hello: " + name + " ,from port:" + port;
    }

    /**
     * 用这个restTemplate调用下游服务，将Authorization传递到下游服务
     * 不然就得编写过滤器已从传入的许可证服务中获取HTTP首部，然后手动将它添加到组织服务的每个出站服务调用中
     *
     * 但是这个restTemplate并不传播基于jwt的令牌，所以需要使用getCustomRestTemplate()方法
     * @param details
     * @return
     */
    @Bean
    public OAuth2RestTemplate oAuth2RestTemplate(
            OAuth2ProtectedResourceDetails details) {
        DefaultOAuth2ClientContext oAuth2ClientContext = new DefaultOAuth2ClientContext();
        return new OAuth2RestTemplate(details, oAuth2ClientContext);
    }

    @Primary
    @Bean
    public RestTemplate getCustomRestTemplate() {
        RestTemplate restTemplate = new RestTemplate();
        List interceptors = restTemplate.getInterceptors();
        if (interceptors == null) {
            restTemplate.setInterceptors(Collections.singletonList(new UserContextInterceptor()));
        } else {
            interceptors.add(new UserContextInterceptor());
            restTemplate.setInterceptors(interceptors);
        }
        return restTemplate;
    }

    /**
     * 从jwt解析自定义字段
     * @param authToken
     * @return
     */
    public String getCustomFieldFromJwt(String authToken) {
        String result = null;
        try {
            Claims body = Jwts.parser()
                    .setSigningKey("key".getBytes())
                    .parseClaimsJws(authToken)
                    .getBody();
            result = (String) body.get("key");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }



}
